package com.qen.encrypt.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import com.qen.encrypt.exception.EncryptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.security.KeyPair;

/**
 * SM2签名
 *
 * @author licz
 * @data 2025年05月27日 3:52 PM
 */
public class SM2Helper implements ParamEncrypt, SignCheck {
    private final Logger log = LoggerFactory.getLogger(getClass());

    private SM2 sm2;

    public SM2Helper(SM2 sm2) {
        this();
    }

    public SM2Helper(byte[] privateKey, byte[] publicKey) {
        this.sm2 = SmUtil.sm2(privateKey, publicKey);
    }

    public SM2Helper(String privateKeyBase64, String publicKeyBase64) {
        this.sm2 = SmUtil.sm2(privateKeyBase64, publicKeyBase64);
    }

    public SM2Helper() {
        this.sm2 = new SM2();
    }

    @Override
    public String pubEncrypt(byte[] data) {
        return sm2.encryptBase64(data, KeyType.PublicKey);
    }

    @Override
    public String pubEncrypt(String data) {
        return sm2.encryptBase64(data, KeyType.PublicKey);
    }

    @Override
    public byte[] priDecrypt(byte[] data) {
        return sm2.decrypt(data, KeyType.PrivateKey);
    }

    @Override
    public String priDecrypt(String data) {
        return sm2.decryptStr(data, KeyType.PrivateKey);
    }

    @Override
    public String priEncrypt(byte[] data) {
        throw new EncryptException("SM2加密方式不支持私钥加密");
    }

    @Override
    public String priEncrypt(String data) {
        throw new EncryptException("SM2加密方式不支持私钥加密");
    }

    @Override
    public byte[] pubDecrypt(byte[] data) {
        throw new EncryptException("SM2加密方式不支持公钥解密");
    }

    @Override
    public String pubDecrypt(String data) {
        throw new EncryptException("SM2加密方式不支持公钥解密");
    }

    @Override
    public void createKey(String outPath) {
        final KeyPair pair = KeyUtil.generateKeyPair("SM2");
        final byte[] privateKey = pair.getPrivate().getEncoded();
        final byte[] publicKey = pair.getPublic().getEncoded();
//        this(privateKey, publicKey);
        this.sm2 = SmUtil.sm2(privateKey, publicKey);
        if (!outPath.endsWith(File.separator)) {
            outPath += File.separator;
        }
        FileUtil.writeBytes(privateKey, outPath + "sm2.pri.pem");
        FileUtil.writeBytes(publicKey, outPath + "sm2.pub.pem");
        log.info("公钥：\n{}", Base64.encode(publicKey));
        log.info("私钥：\n{}", Base64.encode(privateKey));
    }

    @Override
    public String sign(String data) {
        return Base64.encode(sm2.sign(StrUtil.utf8Bytes(data)));
    }

    @Override
    public boolean verify(String srcData, String sign) {
        byte[] bytes = Base64.decode(sign);
        return sm2.verify(StrUtil.utf8Bytes(srcData), bytes);
    }

}
